package com.yisoo.homework.whiteboard.ui.theme;

import com.yisoo.homework.whiteboard.constant.DrawConst;
import com.yisoo.homework.whiteboard.ui.theme.canvas.CanvasTheme;
import com.yisoo.homework.whiteboard.ui.theme.frame.FrameTheme;
import com.yisoo.homework.whiteboard.ui.view.MainFrame;
import javassist.*;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 外部主题策略
 */
@Slf4j
public class ImportThemeStrategy implements ThemeStrategy {
    private static final String PACKAGE_NAME = "com.yisoo.homework.whiteboard.ui.theme.";

    private static Map<String, Object> otherThemeFactoryMap = new ConcurrentHashMap<>();

    @Override
    public void activateTheme(DrawConst.ThemeEnum theme, MainFrame frame) {
        // 参考：javassist,用于字节码编程
        // * 提取类路径
        String classPath = theme.getClassPath();
        // * 创建ClassPool
        ClassPool cp = ClassPool.getDefault();
        String clazzName = PACKAGE_NAME + "factory." + theme.toString() + "OtherThemeFactory";
        CtClass clazz = null;
        Class<?> c = null;
        try {
            if (otherThemeFactoryMap.containsKey(clazzName)) {
                c = (Class<?>) otherThemeFactoryMap.get(clazzName);
            } else {
                // * 生成动态类,不要在异常中处理业务，此处是为了方便
                clazz = cp.makeClass(clazzName);
                // * 完善继承
                assert clazz != null;
                clazz.setSuperclass(cp.getCtClass(PACKAGE_NAME + "factory.ThemeFactory"));
                // * 实现方法createCanvasTheme
                String canvasThemeStr = theme.getIsLight() ? "LightCanvasTheme" : "DarkCanvasTheme";
                String createCanvasTheme = "public com.yisoo.homework.whiteboard.ui.theme.canvas.CanvasTheme createCanvasTheme() {\n" +
                        "return new com.yisoo.homework.whiteboard.ui.theme.canvas." + canvasThemeStr + "();\n}";
                clazz.addMethod(CtMethod.make(createCanvasTheme, clazz));
                // * 实现方法createFrameTheme
                String createFrameTheme = "public com.yisoo.homework.whiteboard.ui.theme.frame.FrameTheme createFrameTheme() {\n" +
                        "return new com.yisoo.homework.whiteboard.ui.theme.frame.OtherFrameTheme(new " + classPath + "());;\n}";
                clazz.addMethod(CtMethod.make(createFrameTheme, clazz));
                // * 创建类对象
                c = clazz.toClass();
                otherThemeFactoryMap.put(clazzName, c);
            }
            Object o = c.newInstance();
            Method frameThemeMethod = o.getClass().getMethod("createFrameTheme");
            Method canvasThemeMethod = o.getClass().getMethod("createCanvasTheme");
            FrameTheme frameTheme = (FrameTheme) frameThemeMethod.invoke(o);
            CanvasTheme canvasTheme = (CanvasTheme) canvasThemeMethod.invoke(o);

            frameTheme.activateFrameTheme(frame);
            canvasTheme.activateCanvasTheme(frame.getCanvas());
        } catch (CannotCompileException | InstantiationException | InvocationTargetException | IllegalAccessException |
                 NoSuchMethodException | NotFoundException e) {
            log.error("主题修改失败");
            throw new RuntimeException(e);
        }
    }
}
